/*
 * @Author: caiwanli 651943559@qq.com
 * @Date: 2023-12-20 15:32:16
 * @LastEditors: caiwanli 651943559@qq.com
 * @LastEditTime: 2024-01-07 21:36:31
 * @FilePath: /task_sche_parser/src/planner/planner.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置
 * 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */

#pragma once

#include "abstract_expression.h"
#include "abstract_plan.h"
#include "binder.h"
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

namespace DaseX {

class BoundStatement;
class SelectStatement;
class DeleteStatement;
class AbstractPlanNode;
class InsertStatement;
class BoundExpression;
class BoundTableRef;
class BoundBinaryOp;
class BoundConstant;
class BoundColumnRef;
class BoundUnaryOp;
class BoundBaseTableRef;
class BoundSubqueryRef;
class BoundCrossProductRef;
class BoundJoinRef;
class BoundExpressionListRef;
class BoundAggCall;
class BoundCTERef;
class ColumnValueExpression;

class PlannerContext {
public:
  PlannerContext() = default;
  void AddAggregation(std::unique_ptr<BoundExpression> expr);
  bool allow_aggregation_{false};
  size_t next_aggregation_{0};
  std::vector<std::unique_ptr<BoundExpression>> aggregations_;

  std::vector<AbstractExpressionRef> expr_in_agg_;

  const CTEList *cte_list_{nullptr};
};



class Planner {
public:
  explicit Planner(CataLog &catalog) : catalog_(catalog) {}

  void PlanQuery(const BoundStatement &statement);

  auto PlanSelect(const SelectStatement &statement) -> AbstractPlanNodeRef;

  auto PlanExpression(const BoundExpression &expr,
                      const std::vector<AbstractPlanNodeRef> &children)
      -> std::tuple<std::string, AbstractExpressionRef>;

  auto PlanBinaryOp(const BoundBinaryOp &expr,
                    const std::vector<AbstractPlanNodeRef> &children)
      -> AbstractExpressionRef;

  auto PlanColumnRef(const BoundColumnRef &expr,
                     const std::vector<AbstractPlanNodeRef> &children)
      -> std::tuple<std::string, std::shared_ptr<ColumnValueExpression>>;

  auto PlanConstant(const BoundConstant &expr,
                    const std::vector<AbstractPlanNodeRef> &children)
      -> AbstractExpressionRef;

  auto PlanTableRef(const BoundTableRef &table_ref) -> AbstractPlanNodeRef;

  auto PlanBaseTableRef(const BoundBaseTableRef &table_ref)
      -> AbstractPlanNodeRef;

  auto PlanCrossProductRef(const BoundCrossProductRef &table_ref)
      -> AbstractPlanNodeRef;

  auto PlanJoinRef(const BoundJoinRef &table_ref) -> AbstractPlanNodeRef;

  auto PlanSelectAgg(const SelectStatement &statement,
                     AbstractPlanNodeRef child) -> AbstractPlanNodeRef;

  AbstractPlanNodeRef plan_;

  CataLog &catalog_;

  PlannerContext ctx_;
};

} // namespace DaseX